/*
 * [y] hybris Platform
 *
 * Copyright (c) 2000-2017 SAP SE
 * All rights reserved.
 *
 * This software is the confidential and proprietary information of SAP
 * Hybris ("Confidential Information"). You shall not disclose such
 * Confidential Information and shall use it only in accordance with the
 * terms of the license agreement you entered into with SAP Hybris.
 */
package acc.asset.sync.task;

import de.hybris.deltadetection.ChangeDetectionService;
import de.hybris.deltadetection.ItemChangeDTO;
import de.hybris.platform.servicelayer.impex.ExportService;
import de.hybris.platform.servicelayer.media.MediaService;
import de.hybris.platform.servicelayer.model.ModelService;
import de.hybris.platform.servicelayer.type.TypeService;
import de.hybris.platform.servicelayer.user.UserService;
import de.hybris.platform.task.RetryLaterException;
import de.hybris.platform.task.TaskModel;
import de.hybris.platform.task.TaskRunner;
import de.hybris.platform.task.TaskService;
import de.hybris.y2ysync.task.dao.Y2YSyncDAO;
import de.hybris.y2ysync.task.runner.TaskContext;
import de.hybris.y2ysync.task.runner.internal.DemoImportScriptCreator;
import de.hybris.y2ysync.task.runner.internal.ExportScriptCreator;
import de.hybris.y2ysync.task.runner.internal.ProcessChangesTask;

import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Required;

import acc.asset.sync.DemoProcessChangesTask;
import acc.asset.sync.creator.DemoExportScriptCreator;


/**
 *
 */
public class DemoItemChangesProcessor implements TaskRunner<TaskModel>
{
	private static final Logger LOG = Logger.getLogger(DemoItemChangesProcessor.class);

	private ModelService modelService;
	private ExportService exportService;
	private MediaService mediaService;
	private ChangeDetectionService changeDetectionService;
	private TypeService typeService;
	private UserService userService;
	private Y2YSyncDAO y2YSyncDAO;

	@Override
	public void run(final TaskService taskService, final TaskModel task) throws RetryLaterException
	{
		this.userService.setCurrentUser(this.userService.getAdminUser());
		final ProcessChangesTask processChangesTask = this.extractTaskFromModel(taskService, task);
		try
		{
			processChangesTask.execute();
		}
		catch (final Exception e)
		{
			LOG.error("Error occured during processing task: " + e);
			throw DemoItemChangesProcessor.createError("Processing changes has failed.", e);
		}
	}

	private ProcessChangesTask extractTaskFromModel(final TaskService taskService, final TaskModel task)
	{
		final TaskContext context = this.extractContextFromModel(task);
		final Collection importScripts = this.getImportScriptCreator(context).createImportScripts();
		return new DemoProcessChangesTask(this.modelService, this.mediaService, this.changeDetectionService, taskService,
				this.typeService, this.y2YSyncDAO, context, importScripts);
	}

	private TaskContext extractContextFromModel(final TaskModel task)
	{
		Map context;
		final Object ctxObject = task.getContext();
		if (ctxObject == null)
		{
			throw DemoItemChangesProcessor.createError("Task doesn't have a context");
		}
		try
		{
			context = (Map) ctxObject;
		}
		catch (final ClassCastException e)
		{
			throw DemoItemChangesProcessor.createError("Couldn't cast a context to an appropriate type", e);
		}
		return new DemoTaskContext(this.modelService, this.mediaService, context);
	}

	@Override
	public void handleError(final TaskService taskService, final TaskModel task, final Throwable error)
	{
		//TODO wei.f.zhang
		LOG.info(error.getMessage(), error);
	}

	@Required
	public void setModelService(final ModelService modelService)
	{
		this.modelService = modelService;
	}

	@Required
	public void setExportService(final ExportService exportService)
	{
		this.exportService = exportService;
	}

	@Required
	public void setMediaService(final MediaService mediaService)
	{
		this.mediaService = mediaService;
	}

	@Required
	public void setChangeDetectionService(final ChangeDetectionService changeDetectionService)
	{
		this.changeDetectionService = changeDetectionService;
	}

	@Required
	public void setTypeService(final TypeService typeService)
	{
		this.typeService = typeService;
	}

	@Required
	public void setUserService(final UserService userService)
	{
		this.userService = userService;
	}

	@Required
	public void setY2YSyncDAO(final Y2YSyncDAO y2YSyncDAO)
	{
		this.y2YSyncDAO = y2YSyncDAO;
	}

	private DemoImportScriptCreator getImportScriptCreator(final TaskContext context)
	{
		List<ItemChangeDTO> changes = Collections.EMPTY_LIST;
		if (context.getMediaPK() != null)
		{
			changes = context.getChanges();
		}
		final ExportScriptCreator exportScriptCreator = new DemoExportScriptCreator(context.getImpExHeader(), context.getTypeCode(),
				changes);
		return new DemoImportScriptCreator(this.modelService, this.exportService, exportScriptCreator, this.userService);
	}

	private static RuntimeException createError(final String message)
	{
		return DemoItemChangesProcessor.createError(message, null);
	}

	private static RuntimeException createError(final String message, final Throwable cause)
	{
		return new RuntimeException(message, cause);
	}

}
